package com.damie.web.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.damie.common.dao.WasteOrder;
import com.damie.common.dao.WasteOrderDetails;
import com.damie.common.paramer.WasteOrderDetailsParamer;
import com.damie.common.paramer.WasteOrderParamer;
import com.damie.web.config.AddressConfig;
import com.damie.web.exception.MyException;
import com.damie.web.mapper.WasteOrderDetailsMapper;
import com.damie.web.mapper.WasteOrderMapper;
import com.damie.web.service.WasteOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.damie.web.utils.JwtUtil;
import com.damie.web.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.GeoOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;


/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ls
 * @since 2021-01-19
 */
@Service
@Slf4j
public class WasteOrderServiceImpl extends ServiceImpl<WasteOrderMapper, WasteOrder> implements WasteOrderService {

    @Autowired
    private WasteOrderMapper wasteOrderMapper;

    @Autowired
    private WasteOrderDetailsMapper wasteOrderDetailsMapper;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private AddressConfig addressConfig;

    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    private ScheduledFuture<?> future1;

    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        return new ThreadPoolTaskScheduler();
    }

    /**
     * 查看用户生成的所有订单
     * @param wasteOrderParamer
     * @return
     */
    public List<WasteOrder> findAll(WasteOrderParamer wasteOrderParamer){
        WasteOrder wasteOrder = new WasteOrder();
        BeanUtils.copyProperties(wasteOrderParamer,wasteOrder);
        QueryWrapper<WasteOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("waste_order_status",1);
        List<WasteOrder> wasteOrderList = wasteOrderMapper.selectList(queryWrapper);
        return wasteOrderList;
    }


    /**
     * 分页查看用户生成的订单
     * @param wasteOrderParamer
     * @return
     */
    public Page<WasteOrder> getPageVo(Page<WasteOrder> iPage,WasteOrderParamer wasteOrderParamer){
//        http://localhost:5000/waste-order/page/2/2
        WasteOrder wasteOrder = new WasteOrder();
        BeanUtils.copyProperties(wasteOrderParamer,wasteOrder);
        QueryWrapper<WasteOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("waste_order_status",1);
        Page<WasteOrder> page = wasteOrderMapper.getPageVo(iPage,queryWrapper);
        return page;
    }

    /**
     * 分页查看本站点未完成的订单
     * @param myOrder
     * @return
     */
    public Page<MyOrder> unFinish(Page<MyOrder> iPage, MyOrder myOrder, HttpServletRequest httpServletRequest){
        String token = httpServletRequest.getHeader("token");
        String userId = JwtUtil.getUserId(token);
        System.out.println("用户id:++++++++"+userId);

        QueryWrapper<MyOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("t1.waste_order_status",2);
        queryWrapper.eq("t2.user_id",userId);
        Page<MyOrder> page = wasteOrderMapper.MyOrder(iPage, queryWrapper);
        return page;
    }

    public Page<MyOrder> finish(Page<MyOrder> iPage, MyOrder myOrder, HttpServletRequest httpServletRequest){
        String token = httpServletRequest.getHeader("token");
        String userId = JwtUtil.getUserId(token);
        System.out.println("用户id:++++++++"+userId);

        QueryWrapper<MyOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("t1.waste_order_status",3);
        queryWrapper.eq("t2.user_id",userId);
        Page<MyOrder> page = wasteOrderMapper.MyOrder(iPage, queryWrapper);
        return page;
    }

    public Page<MyOrder> cancel(Page<MyOrder> iPage, MyOrder myOrder, HttpServletRequest httpServletRequest){
        String token = httpServletRequest.getHeader("token");
        String userId = JwtUtil.getUserId(token);
        System.out.println("用户id:++++++++"+userId);

        QueryWrapper<MyOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("t1.waste_order_status",4);
        queryWrapper.eq("t2.user_id",userId);
        Page<MyOrder> page = wasteOrderMapper.MyOrder(iPage, queryWrapper);
        return page;
    }

    /**
     * 站点开始接单修改订单状态为已接单
     * @param wasteOrderParamer
     * @return
     */
    public String orderTaking(WasteOrderParamer wasteOrderParamer,String lockKey){
        RLock lock=null;
        boolean b=true;
        try{
            System.out.println(lockKey);
            lock = redissonClient.getLock(lockKey);
            b = lock.tryLock();
            log.info("加锁成功{}",b);
            System.out.println(lock);
            WasteOrder wasteOrder = new WasteOrder();
            BeanUtils.copyProperties(wasteOrderParamer,wasteOrder);
            QueryWrapper<WasteOrder> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("waste_order_status",1);//筛选出还未接单的订单
            List<WasteOrder> wasteOrderList = wasteOrderMapper.selectList(queryWrapper);
            System.out.println(wasteOrderList);
            if (ObjectUtils.isEmpty(wasteOrderList)){
                throw new MyException(500,"当前没有可选的订单");
            }
            wasteOrderParamer.setWasteOrderStatus(2);
            //redis中记录 0=》未接单 1 =》接单
            stringRedisTemplate.opsForValue().increment("press:"+wasteOrder.getWasteOrderId());

            BeanUtils.copyProperties(wasteOrderParamer,wasteOrder);
            wasteOrderMapper.orderTaking(wasteOrder);
        }catch (MyException e){
            e.printStackTrace();
        }finally {
            log.info("准备解锁{}",b);
            lock.unlock();
            log.info("解锁完成");
        }
        return "success";
    }


    /**
     * 查询用户与站点的经纬度信息并计算距离
     * @param wasteOrderId
     * @return
     */
    public Distance findAddress(String wasteOrderId){
//        1351465434128019458
        Distance address = wasteOrderMapper.findAddress(wasteOrderId);
        if (ObjectUtils.isEmpty(address)){
            throw new MyException(500,"无法查询到此地信息");
        }

        final double[] userLongitude = {address.getAddressLongitude()};
        final double[] userLatitude = {address.getAddressLatitude()};
        System.out.println("用户经度:"+userLongitude[0]+"||用户纬度:"+userLatitude[0]);

        final double[] siteLongitude = {address.getSiteLongitude()};
        final double[] siteLatitude = {address.getSiteLatitude()};
        System.out.println("站点经度:"+ siteLongitude[0] +"||站点纬度:"+ siteLatitude[0]);

        System.out.println("司机出发");
        Runnable runnable = new Runnable() {
            public void run() {
                // task to run goes here
                siteLongitude[0]=siteLongitude[0]-0.0005;
                siteLatitude[0]=siteLatitude[0]-0.0005;
                BigDecimal bigDecimal = new BigDecimal(siteLongitude[0]);
                double decimal = bigDecimal.setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue();//站点经度四舍五入
                BigDecimal bigDecimal1 = new BigDecimal(siteLatitude[0]);
                double decimal1 = bigDecimal1.setScale(6, BigDecimal.ROUND_HALF_UP).doubleValue();//站点纬度四舍五入
                System.out.println("站点经度:"+ decimal +"||站点纬度:"+ decimal1);


                GeoOperations geoOperations = stringRedisTemplate.opsForGeo();
                //首先存入用户的经纬度和站点的经纬度
                HashMap<Object, Object> map = new HashMap<>();
                //存入用户经纬度
                map.put("user",new Point(userLongitude[0],userLatitude[0]));//用户位置不变
                //存入司机经纬度
                map.put("site",new Point(decimal, decimal1));//司机的位置一直在动
                //将这些数据保存到redis中
                geoOperations.add("distance",map);
                stringRedisTemplate.expire("distance",3, TimeUnit.SECONDS);

//                BoundGeoOperations boundGeoOperations = stringRedisTemplate.boundGeoOps("distance");
//                List user = boundGeoOperations.position("user");
//                List site = boundGeoOperations.position("site");
//                System.out.println("用户坐标"+user);
//                System.out.println("站点坐标"+site);

                //调用方法,计算用户与站点之间的距离
                double km = geoOperations.distance("distance", "user", "site", Metrics.KILOMETERS).getValue();
                System.out.println("司机到用户的距离是"+km+"km");
                if (km<0.99){
                    System.out.println("司机到达");
                    future1.cancel(true);
                }
            }
        };
        future1 = threadPoolTaskScheduler.schedule(runnable,new Trigger(){
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext){
                return new CronTrigger(addressConfig.getCorn1()).nextExecutionTime(triggerContext);
            }
        });
        return address;
    }

    /**
     * 查询订单详情
     * @param
     * @return
     */
    public OrderDetails findOne(String wasteOrderId){
        List<WasteOrderDetailsVo> allWasteOrderDetails = wasteOrderMapper.findAllWasteOrderDetails(wasteOrderId);
        String addressName = wasteOrderMapper.addressName(wasteOrderId);
        WasteOrder wasteOrder = wasteOrderMapper.selectById(wasteOrderId);
        OrderDetails orderDetails = new OrderDetails();
        BeanUtils.copyProperties(wasteOrder,orderDetails);
        orderDetails.setWasteOrderDetailsVos(allWasteOrderDetails);
        orderDetails.setAddressName(addressName);
        return orderDetails;
    }

    public int updateWasteOrder(WasteOrderVo wasteOrderVo){
        WasteOrder wasteOrder = wasteOrderMapper.findOne2(wasteOrderVo.getWasteOrderId());
        System.out.println(wasteOrder);
        if (ObjectUtils.isEmpty(wasteOrder)){
            throw new MyException(500,"订单查询不到");
        }else if (wasteOrder.getWasteOrderStatus()==3){
            throw new MyException(500,"订单已完成无需修改");
        }else if(wasteOrder.getWasteOrderStatus()==4){
            throw new MyException(500,"订单已被取消,无法操作");
        }

        QueryWrapper<WasteOrderDetails> queryWrapper= new QueryWrapper<>();
        queryWrapper.eq("waste_order_id",wasteOrder.getWasteOrderId());
        List<WasteOrderDetails> wasteOrderDetails = wasteOrderDetailsMapper.selectList(queryWrapper);

        List<WasteOrderDetailsVo> vos = wasteOrderVo.getWasteOrderDetailsVos();

        for (WasteOrderDetails w:wasteOrderDetails){
            System.out.println("查出来的"+w);
            for (WasteOrderDetailsVo v:vos){
                System.out.println("传进来"+v);
                if (w.getWasteOrderDetailsId().equals(v.getWasteOrderDetailsId())){
                    Integer wasteNumber = v.getWasteNumber();
                    double wastePrice = v.getWastePrice();
                    String wasteOrderDetailsId = v.getWasteOrderDetailsId();

                    System.out.println("废品数量:"+wasteNumber+"||废品价格:"+wastePrice);

                    WasteOrderDetailsVo wasteOrderDetailsVo = new WasteOrderDetailsVo();
                    wasteOrderDetailsVo.setWasteNumber(wasteNumber);
                    wasteOrderDetailsVo.setWastePrice(wastePrice);
                    wasteOrderDetailsVo.setWasteOrderDetailsId(wasteOrderDetailsId);

                    wasteOrderMapper.updateWasteOrderDetails(wasteOrderDetailsVo);
                }
            }
        }
        wasteOrderVo.setWasteOrderStatus(3);
        wasteOrderMapper.updateWasteOrder(wasteOrderVo);
        return 1;
    }

    public int updateWasteOrderDetails1(WasteOrderDetailsVo wasteOrderDetailsVo){
        wasteOrderMapper.updateWasteOrderDetails1(wasteOrderDetailsVo);
        return 1;
    }

    public int updateWasteOrder1(WasteOrderVo1 wasteOrderVo1){
        WasteOrder wasteOrder = wasteOrderMapper.findOne1(wasteOrderVo1.getWasteOrderId());
        if (ObjectUtils.isEmpty(wasteOrder)){
            throw new MyException(500,"订单查询不到");
        }else if (wasteOrder.getWasteOrderStatus()==3){
            throw new MyException(500,"订单已完成无需修改");
        }else if(wasteOrder.getWasteOrderStatus()==4){
            throw new MyException(500,"订单已被取消,无法操作");
        }

        wasteOrderVo1.setWasteOrderStatus(3);
        wasteOrderMapper.updateWasteOrder1(wasteOrderVo1);
        return 1;
    }

}
